<template>
  <template v-if="hasChildren">
    <component
      v-if="shouldTransferStyles"
      :is="childComponent"
      :class="computedClass"
      :style="computedStyle"
      @click="onClick"
    />
    <div v-else :class="computedClass" :style="computedStyle" @click="onClick">
      <slot />
    </div>
  </template>
</template>

<script setup>
import { computed, inject, useSlots } from 'vue';

const props = defineProps({
  class: String,
  colSpan: { type: Number, default: 1 },
  rowSpan: { type: Number, default: 1 },
  transferStyle: Boolean,
  style: Object,
  onClick: Function,
});

const { defaultTransferStyle } = inject('GridContext', {});

const slots = useSlots();
const hasChildren = computed(() => !!slots.default?.().length);

const computedClass = computed(() => ['grid-item', props.class]);
const computedStyle = computed(() => ({
  ...(props.colSpan > 1 && { gridColumn: `span ${props.colSpan}` }),
  ...(props.rowSpan > 1 && { gridRow: `span ${props.rowSpan}` }),
  ...props.style,
}));

const shouldTransferStyles = computed(
  () => (defaultTransferStyle || props.transferStyle) && hasChildren.value && isSingleElement(slots),
);

function isSingleElement(slots) {
  const children = slots.default?.();
  return children?.length === 1 && children[0].type !== 'template';
}

const childComponent = computed(() => {
  if (!shouldTransferStyles.value) return null;
  const [child] = slots.default();
  return {
    ...child,
    props: {
      ...child.props,
      class: [child.props?.class, ...computedClass.value].filter(Boolean).join(' '),
      style: { ...child.props?.style, ...computedStyle.value },
    },
  };
});
</script>

<style>
.grid-item {
  position: relative;
}
</style>
